package com.youlu.campus.web.university.service.impl;

import com.alibaba.fastjson.JSON;
import com.youlu.campus.base.base.PageQueryRequest;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.base.group.enums.GroupStatusEnum;
import com.youlu.campus.base.user.WechatMenu;

import com.youlu.campus.entity.ActivityUserRecord;
import com.youlu.campus.entity.SystemApolloConfig;
import com.youlu.campus.entity.UniversityInfo;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.entity.VO.req.UniversityReq;
import com.youlu.campus.service.base.BaseService;
import com.youlu.campus.service.system.SystemApolloConfigService;
import com.youlu.campus.service.utils.IkAnalyzerUtil;
import com.youlu.campus.web.common.base.RequestContext;
import com.youlu.campus.web.qq.QQService;
import com.youlu.campus.web.group.entity.GroupPO;
import com.youlu.campus.web.group.service.GroupService;
import com.youlu.campus.web.university.dto.UniversityQueryDTO;
import com.youlu.campus.web.university.dto.UniversityRankResponse;
import com.youlu.campus.web.university.dto.UniversityResponse;
import com.youlu.campus.web.university.entity.UniversityPO;
import com.youlu.campus.web.university.service.UniversityService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.TextCriteria;
import org.springframework.data.mongodb.core.query.TextQuery;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 学校管理接口实现类
 *
 * @author zgz
 * @date 2020/11/28 11:48
 */
@Slf4j
@Service("universityService")
public class UniversityServiceImpl extends BaseService implements UniversityService {

    @Autowired
    private GroupService groupService;
    @Autowired
    private QQService qqService;
    @Autowired
    private SystemApolloConfigService systemApolloConfigService;

    private final static String LOGO = "https://qiniu.gqgood.com/imgfb2fbd3021624202bb1d5386ecb1eb79university-default-logo.jpg";

    @Override
    public List<UniversityPO> findAllByName(UniversityQueryDTO queryDTO) {
        log.info(":>>> 开始查询大学信息:{}", JSON.toJSONString(queryDTO));
        long start = System.nanoTime();
        String universityName = queryDTO.getName();
        if (StringUtils.isBlank(universityName) || StringUtils.isBlank(universityName.trim())) {
            Query query = new Query();
            query.limit(20);
            query.addCriteria(Criteria.where("deleted").is(false));
            query.addCriteria(Criteria.where("dataType").in(1,2));
            log.info("query university used time:{}ms",(System.nanoTime()-start)/1000000);
            return mongoTemplate.find(query, UniversityPO.class);
        }
//        Config config = ConfigService.getAppConfig();
//        String cnf = config.getProperty("wechat.menu", "{}");
//        WechatMenu wechatMenu = JSON.parseObject(cnf,WechatMenu.class);
        SystemApolloConfig systemApolloConfig = systemApolloConfigService.find();
        WechatMenu wechatMenu=systemApolloConfig.getWechatMenu();
        if(wechatMenu.getUsedIkSearch()){
            Set<String> names = IkAnalyzerUtil.getSegText(universityName,true);
            List<String> excludeWords = wechatMenu.getExcludeWords();
            if(!CollectionUtils.isEmpty(excludeWords) && (names.size() >= wechatMenu.getWordsNum() || universityName.length() >= wechatMenu.getWordsLength())){
                names = names.stream().filter(words->!(excludeWords.contains(words))).collect(Collectors.toSet());
            }
            String ak = wechatMenu.getSearchType() == 0 ? IkAnalyzerUtil.getSegTextStr(names):IkAnalyzerUtil.getAndStr(names);
            TextCriteria textCriteria = TextCriteria.forDefaultLanguage();
            textCriteria.matching(ak);
            Query query = TextQuery.queryText(textCriteria).sortByScore();
            query.addCriteria(Criteria.where("deleted").is(false));
            query.addCriteria(Criteria.where("dataType").in(1,2));
            query.limit(wechatMenu.getNum());
            log.info("query university ak:{}",ak);
            List<UniversityPO> list = mongoTemplate.find(query,UniversityPO.class);
            log.info("query university used time:{}ms",(System.nanoTime()-start)/1000000);
            return list;
        }
        Query query = new Query();
        query.limit(20);
        query.addCriteria(Criteria.where("deleted").ne(true));
        query.addCriteria(Criteria.where("dataType").ne(3));
        Pattern pattern = Pattern.compile("^.*" + queryDTO.getName() + ".*$", Pattern.CASE_INSENSITIVE);
        query.addCriteria(Criteria.where("name").regex(pattern));
        List<UniversityPO> list = mongoTemplate.find(query,UniversityPO.class);
        log.info("query university used time:{}ms",(System.nanoTime()-start)/1000000);
        return list;
    }


    @Override
    public Page<UniversityRankResponse> getUniversityRankPage(PageQueryRequest request) {
        UserPO userPO = RequestContext.getCurUser();
        log.info("getUniversityRankPage userId {} request {}", userPO.getId(), request);
        Query query = new Query();
        query.addCriteria(Criteria.where("deleted").is(false));
        query.addCriteria(Criteria.where("dataType").ne(2));
        long count = mongoTemplate.count(query, UniversityPO.class);
        PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "activeValue"));
        Sort sort=Sort.by(Sort.Direction.DESC, "activeValue");
        query.with(sort);
        List<UniversityPO> universityPOList = mongoTemplate.find(query.with(pageRequest), UniversityPO.class);
        int rank = (request.getPage() - 1) * request.getPageSize();
        List<UniversityRankResponse> list = new ArrayList<>();
        for (UniversityPO universityPO : universityPOList) {
            UniversityRankResponse response = new UniversityRankResponse();
            BeanUtils.copyProperties(universityPO, response);
            //获取组织数量
            response.setGroupCount(groupService.getUniversityGroupCount(universityPO.getValue()).intValue());
            if (StringUtils.isNotBlank(userPO.getUniversityValue())) {
                response.setMine(userPO.getUniversityValue().equals(universityPO.getValue()));
            }
            Query gquery = new Query();
            gquery.addCriteria(Criteria.where("deleted").is(false));
            gquery.addCriteria(Criteria.where("status").ne(GroupStatusEnum.DISSOLUTION.getValue()));
            gquery.addCriteria(Criteria.where("universityValue").is(universityPO.getValue()));
            PageRequest gpageRequest = PageRequest.of(0, 1);
//            gquery.with(new Sort(Sort.Direction.DESC, "activeValue"));
            Sort sortQQ=Sort.by(Sort.Direction.DESC, "activeValue");
            gquery.with(sortQQ);
            List<GroupPO> groupPOList = mongoTemplate.find(gquery.with(gpageRequest), GroupPO.class);
            if (!CollectionUtils.isEmpty(groupPOList)) {
                response.setBestGroupName(groupPOList.get(0).getName());
                response.setBestGroupId(groupPOList.get(0).getId());
            }
            rank++;
            response.setRank(rank);
            list.add(response);
        }
        //获取我所在大学排行榜
        UniversityRankResponse my = this.getMyUniversityRank(userPO);
        if (my != null && request.getPage() == 1) {
            list.add(0, my);
        }
        return PageableExecutionUtils.getPage(list, pageRequest, () -> count);

    }

    @Override
    public UniversityResponse getUniversityInfo(String universityValue) {
        UniversityResponse response = new UniversityResponse();
        //获取学校信息
        Query uquery = new Query();
        uquery.addCriteria(Criteria.where("value").is(universityValue));
        UniversityPO universityPO = mongoTemplate.findOne(uquery, UniversityPO.class);
        if (universityPO != null) {
            response.setUniversityValue(universityValue);
            response.setUniversityName(universityPO.getName());
            response.setLogo(universityPO.getLogo());
        }
        return response;
    }

    @Override
    public UniversityPO getById(String id) {
        log.info(":>>> 开始查询大学:{}", id);
        Query query1 = new Query().addCriteria(Criteria.where("id").is(id));
        UniversityPO universityPO = mongoTemplate.findOne(query1, UniversityPO.class);
        log.info(":>>> 大学信息:{},{}", id, JSON.toJSONString(universityPO));
        return universityPO;
    }

    @Override
    public UniversityInfo getUniversity(UserPO userPO, String mobile) {
        log.info(":>>> 开始获取大学信息:{},{}", mobile, JSON.toJSONString(userPO));
        UniversityInfo universityInfo = null;
        try {
            if (StringUtils.isNotBlank(mobile)) {
                Query query = new Query().addCriteria(Criteria.where("mobile").is(mobile));
                ActivityUserRecord record = mongoTemplate.findOne(query, ActivityUserRecord.class);
                if (Objects.nonNull(record)) {
                    if (StringUtils.isNotBlank(record.getUniversityName())) {
                        Query queryU = new Query().addCriteria(Criteria.where("name").is(record.getUniversityName()));
                        universityInfo = mongoTemplate.findOne(queryU, UniversityInfo.class);
                    }
                }
            }
            if (Objects.isNull(universityInfo)) {
                if (StringUtils.isNotBlank(userPO.getUniversityId())) {
                    Query query1 = new Query().addCriteria(Criteria.where("id").is(userPO.getUniversityId()));
                    universityInfo = mongoTemplate.findOne(query1, UniversityInfo.class);
                }
            }
        } catch (Exception e) {
            log.error(":>>> 获取大学信息错误:{}", e);
        }
        return universityInfo;
    }

    @Override
    public UniversityInfo saveOrUpdate(UniversityInfo updateUniversity) {
        if (StringUtils.isBlank(updateUniversity.getName())) {
            throw new BusinessException("学校名称不能为空");
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("name").is(updateUniversity.getName()));
        Date now = new Date();
        Update update = new Update();
        update.setOnInsert("createdTime", now);
        update.setOnInsert("deleted", false);
        update.set("dataType", 3);
        update.set("value", updateUniversity.getName());
        update.set("updatedTime", now);
        Set<String> names = IkAnalyzerUtil.getSegText(updateUniversity.getName(),true);
        update.set("nameKeywords",names);
        update.set("nameKeys",IkAnalyzerUtil.getSegTextStr(names));
        FindAndModifyOptions findAndModifyOptions = new FindAndModifyOptions();
        findAndModifyOptions.returnNew(Boolean.TRUE);
        findAndModifyOptions.upsert(Boolean.TRUE);
        return this.mongoTemplate.findAndModify(query, update, findAndModifyOptions, UniversityInfo.class);
    }

    @Override
    public UniversityInfo findModify(UniversityReq universityReq) {
        String name = universityReq.getName();
        log.info("【学校】输入填写 userId ->{} | name->{}", universityReq.getCurrentUserId(), name);
        if (StringUtils.isBlank(name)) {
            throw new BusinessException("学校名称不能为空");
        }
        if (qqService.hasIllegal(name)) {
            log.error("【学校名称非法】提交用户->{},学校名称->{}",universityReq.getCurrentUserId(),name);
            throw new BusinessException("请输入正确的学校名称");
        }
        name = name.trim();
        Query query = new Query();
        query.addCriteria(Criteria.where("name").is(name));
        UniversityInfo university = this.mongoTemplate.findOne(query, UniversityInfo.class);
        if(Objects.nonNull(university)){
            return university;
        }
        Date now = new Date();
        Update update = new Update();
        update.setOnInsert("createdTime", now);
        update.setOnInsert("deleted", false);
        update.set("dataType", 1);
        update.set("logo",LOGO);
        update.set("province",universityReq.getProvince());
        update.set("updatedTime", now);
        update.set("value",name);
        Set<String> names = IkAnalyzerUtil.getSegText(name,true);
        update.set("nameKeywords",names);
        update.set("nameKeys",IkAnalyzerUtil.getSegTextStr(names));
        FindAndModifyOptions findAndModifyOptions = new FindAndModifyOptions();
        findAndModifyOptions.returnNew(Boolean.TRUE);
        findAndModifyOptions.upsert(Boolean.TRUE);
        return this.mongoTemplate.findAndModify(query, update, findAndModifyOptions, UniversityInfo.class);
    }

    private UniversityRankResponse getMyUniversityRank(UserPO userPO) {
        Query query = new Query();
        query.addCriteria(Criteria.where("deleted").is(false));
        PageRequest pageRequest = PageRequest.of(0, 10000);
//        query.with(new Sort(Sort.Direction.DESC, "activeValue"));
        Sort sort=Sort.by(Sort.Direction.DESC, "activeValue");
        query.with(sort);
        List<UniversityPO> universityPOList = mongoTemplate.find(query.with(pageRequest), UniversityPO.class);
        for (int i = 0; i < universityPOList.size(); i++) {
            UniversityPO universityPO = universityPOList.get(i);
            if (universityPO.getValue().equals(userPO.getUniversityValue())) {
                UniversityRankResponse response = new UniversityRankResponse();
                BeanUtils.copyProperties(universityPO, response);
                //获取组织数量
                response.setGroupCount(groupService.getUniversityGroupCount(universityPO.getValue()).intValue());
                if (StringUtils.isNotBlank(userPO.getUniversityValue())) {
                    response.setMine(userPO.getUniversityValue().equals(universityPO.getValue()));
                }
                Query gquery = new Query();
                gquery.addCriteria(Criteria.where("deleted").is(false));
                gquery.addCriteria(Criteria.where("status").ne(GroupStatusEnum.DISSOLUTION.getValue()));
                gquery.addCriteria(Criteria.where("universityValue").is(universityPO.getValue()));
                PageRequest gpageRequest = PageRequest.of(0, 1);
//                gquery.with(new Sort(Sort.Direction.DESC, "activeValue"));
                Sort sortgq=Sort.by(Sort.Direction.DESC, "activeValue");
                gquery.with(sortgq);
                List<GroupPO> groupPOList = mongoTemplate.find(gquery.with(gpageRequest), GroupPO.class);
                if (!CollectionUtils.isEmpty(groupPOList)) {
                    response.setBestGroupName(groupPOList.get(0).getName());
                    response.setBestGroupId(groupPOList.get(0).getId());
                }
                response.setRank(i + 1);
                return response;
            }
        }
        return null;
    }
}
